;;; init.el --- The main init entry for Emacs -*- lexical-binding: t -*-
;;; Commentary:

;;; Code:

(defvar elpaca-installer-version 0.11)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
                              :ref nil :depth 1 :inherit ignore
                              :files (:defaults "elpaca-test.el" (:exclude "extensions"))
                              :build (:not elpaca--activate-package)))
(let* ((repo  (expand-file-name "elpaca/" elpaca-repos-directory))
       (build (expand-file-name "elpaca/" elpaca-builds-directory))
       (order (cdr elpaca-order))
       (default-directory repo))
  (add-to-list 'load-path (if (file-exists-p build) build repo))
  (unless (file-exists-p repo)
    (make-directory repo t)
    (when (<= emacs-major-version 28) (require 'subr-x))
    (condition-case-unless-debug err
        (if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
                  ((zerop (apply #'call-process `("git" nil ,buffer t "clone"
                                                  ,@(when-let* ((depth (plist-get order :depth)))
                                                      (list (format "--depth=%d" depth) "--no-single-branch"))
                                                  ,(plist-get order :repo) ,repo))))
                  ((zerop (call-process "git" nil buffer t "checkout"
                                        (or (plist-get order :ref) "--"))))
                  (emacs (concat invocation-directory invocation-name))
                  ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
                                        "--eval" "(byte-recompile-directory \".\" 0 'force)")))
                  ((require 'elpaca))
                  ((elpaca-generate-autoloads "elpaca" repo)))
            (progn (message "%s" (buffer-string)) (kill-buffer buffer))
          (error "%s" (with-current-buffer buffer (buffer-string))))
      ((error) (warn "%s" err) (delete-directory repo 'recursive))))
  (unless (require 'elpaca-autoloads nil t)
    (require 'elpaca)
    (elpaca-generate-autoloads "elpaca" repo)
    (let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))

(setq elpaca-queue-limit 5)             ; Fix "Too many open files"

;; Windows users must be able to create symlinks1, or enable elpaca-no-symlink-mode
(when (eq system-type 'windows-nt)
  (elpaca-no-symlink-mode))

;; Install use-package support
(elpaca elpaca-use-package
  ;; Enable use-package :ensure support for Elpaca.
  (elpaca-use-package-mode))

;; 统计插件加载时间
(use-package benchmark-init
  :ensure t
  :init (benchmark-init/activate)
  :hook
  ;; To disable collection of benchmark data after init is done.
  (elpaca-after-init . benchmark-init/deactivate))

;; 统计各个配置文件的加载时间
(use-package esup
  :ensure t
  :commands (esup)
  :config
  (setq esup-depth 0))

;; Org 文件保存时自动执行导出
(defun +config--org-babel-tangle-config ()
  "Export emacs config when config org file is saved"
  (when (string-equal (buffer-file-name)
                      (expand-file-name "emacs-config.org" user-emacs-directory))
    (let ((org-confirm-babel-evaluate nil))
      (org-babel-tangle))))
(add-hook 'org-mode-hook
          (lambda () (add-hook 'after-save-hook #'+config--org-babel-tangle-config nil 'local)))

;; 生成 autoloads 函数
(defun +config--generate-autoloads ()
  "Generate autoloads for all .el files in lisp/ directory"
  (when (string-equal (buffer-file-name)
                      (expand-file-name "emacs-config.org" user-emacs-directory))
    (let* ((lisp-dir (expand-file-name "lisp/" user-emacs-directory))
           (output-file (expand-file-name "loaddefs.el" lisp-dir))
           (backup-inhibited t)
           (make-backup-files nil)
           (excluded-files nil)
           (extra-data nil)
           (include-package-version nil)
           (generate-full nil))
      (unless (file-directory-p lisp-dir)
        (make-directory lisp-dir t))
      (when (file-exists-p output-file)
        (delete-file output-file))
      (loaddefs-generate lisp-dir output-file
                         excluded-files
                         extra-data
                         include-package-version
                         generate-full)
      (message "Autoloads generated in %s" output-file))))
(add-hook 'org-mode-hook
          (lambda () (add-hook 'after-save-hook #'+config--generate-autoloads nil 'local)))

;; 将 lisp 目录放到加载路径的前面以加快启动速度
(let ((dir (locate-user-emacs-file "lisp")))
  (add-to-list 'load-path (file-name-as-directory dir)))

;; 加载 autoload
(load "loaddefs" nil t)

;; 加载其他模块
(require 'init-generic)
(require 'init-base)
(require 'init-ui)
(require 'init-edit)
(require 'init-minibuffer)
(require 'init-wm)
(require 'init-tools)
(require 'init-org)
(require 'init-coding)
(require 'init-vc)
(require 'init-keymap)
(require 'init-lang)

(provide 'init)
;;; init.el ends here
